use axum::routing::{get, post};
use axum::{Json, Router, extract};
use bytes::Bytes;
use serde::Deserialize;

use crate::router::api::i_router::IRouter;
use crate::router::api::params_query::Info;

#[derive(Deserialize, Debug)]
struct User {
    email: String,
    password: String,
}

// 共享状态结构体
#[derive(Debug)]
pub struct BodyParams {}

impl IRouter for BodyParams {
    fn init_router(&self, router: Router) -> Router {
        let gg = Router::new()
            .route("/json", post(BodyParams::json))
            .route("/string", post(BodyParams::string))
            .route("/bytes", post(BodyParams::bytes))
            .route("/request", post(BodyParams::request))
            .route("/form", post(BodyParams::form))
            .route("/raw_form", post(BodyParams::raw_form))
            .route("/connect_info", get(BodyParams::connect_info))
            .route("/all/:name", post(BodyParams::all));
        router.nest("/body", gg)
    }
}

impl BodyParams {
    pub fn new() -> BodyParams {
        BodyParams {}
    }
    async fn json(Json(payload): Json<User>) {
        println!("{:?}", payload)
    }
    async fn string(body: String) {
        println!("{}", body);
    }
    async fn bytes(body: Bytes) {
        println!("{:?}", body)
    }
    async fn request(request: extract::Request) {
        println!("{:?}", request)
    }
    async fn form(from: extract::Form<User>) {
        println!("{:?}", from)
    }
    async fn raw_form(raw_form: extract::RawForm) {
        println!("{:?}", raw_form)
    }
    async fn connect_info(
        extract::ConnectInfo(addr): extract::ConnectInfo<std::net::SocketAddr>,
    ) -> String {
        format!("Hello {addr}")
    }

    // `Extension` extracts data from "request extensions"
    // This is commonly used to share state with handlers
    async fn all(
        query: extract::Query<Info>,
        extract::Path(path): extract::Path<String>,
        extract::Json(user): extract::Json<User>,
    ) {
        println!("{:?},{:?},{:?}", query, path, user,)
    }

    // 方法2: 使用 Extension 请求扩展提取器
    // 这种方法的缺点是，如果尝试提取一个不存在的扩展，可能是因为忘记添加中间件，
    // 或者因为提取了错误的类型，那么将得到运行时错误(特别是500 Internal Server Error 响应)。
}
